Skip to content

Conversation

@fursov
Copy link

@fursov fursov commented Sep 15, 2024

If the type of an enumeration is not native (e.g. uint8_t) but is unsigned then evaluation of the value might get wrong: for values bigger than half of type range the return value will be negative. This happens because for non-native enum types the TypeKind is ELABORATED. To get the real integer type, the conversion to canonical type is required before the enum_value() function can decide about type being signed or unsigned.

If the type of an enumeration is not native (e.g. uint8_t) but
is unsigned then evaluation of the value might get wrong: for
values bigger than half of type range the return value will be
negative. This happens because for non-native enum types the TypeKind
is ELABORATED. To get the real integer type, the conversion to
canonical type is required before the enum_value() function can
decide about type being signed or unsigned.
@github-actions
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added the clang Clang issues not falling into any other category label Sep 15, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 15, 2024

@llvm/pr-subscribers-clang

Author: Dmitry Fursov (fursov)

Changes

If the type of an enumeration is not native (e.g. uint8_t) but is unsigned then evaluation of the value might get wrong: for values bigger than half of type range the return value will be negative. This happens because for non-native enum types the TypeKind is ELABORATED. To get the real integer type, the conversion to canonical type is required before the enum_value() function can decide about type being signed or unsigned.


Full diff: https://github.com/llvm/llvm-project/pull/108768.diff

2 Files Affected:

  • (modified) clang/bindings/python/clang/cindex.py (+2)
  • (modified) clang/bindings/python/tests/cindex/test_cursor.py (+19)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 754f03d718e882..67215f0b7fdcb7 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1831,6 +1831,8 @@ def enum_value(self):
             underlying_type = self.type
             if underlying_type.kind == TypeKind.ENUM:
                 underlying_type = underlying_type.get_declaration().enum_type
+            if underlying_type.kind == TypeKind.ELABORATED:
+                underlying_type = underlying_type.get_canonical()
             if underlying_type.kind in (
                 TypeKind.CHAR_U,
                 TypeKind.UCHAR,
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index 84cd8139418447..5cb3e638c94a60 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -511,6 +511,25 @@ def test_enum_values_cpp(self):
         self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)
         self.assertEqual(ham.enum_value, 0x10000000000)
 
+    def test_enum_values_on_elaborated_type(self):
+        tu = get_tu(
+            "using myUType = unsigned char; enum TEST : myUType { SPAM = 1, HAM = 0xff;", lang="cpp"
+        )
+        enum = get_cursor(tu, "TEST")
+        self.assertIsNotNone(enum)
+
+        self.assertEqual(enum.kind, CursorKind.ENUM_DECL)
+
+        enum_constants = list(enum.get_children())
+        self.assertEqual(len(enum_constants), 2)
+
+        spam, ham = enum_constants
+
+        self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL)
+        self.assertEqual(spam.enum_value, 1)
+        self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)
+        self.assertEqual(ham.enum_value, 255)
+
     def test_annotation_attribute(self):
         tu = get_tu(
             'int foo (void) __attribute__ ((annotate("here be annotation attribute")));'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants